package fun.boomcat.luckyhe.mirai.plugin.command;

import fun.boomcat.luckyhe.mirai.plugin.config.RconCommandConfigOperation;
import fun.boomcat.luckyhe.mirai.plugin.pojo.CommandMapping;
import fun.boomcat.luckyhe.mirai.plugin.pojo.Player;
import fun.boomcat.luckyhe.mirai.plugin.service.CommandMappingService;
import fun.boomcat.luckyhe.mirai.plugin.service.CommandMappingServiceImpl;
import fun.boomcat.luckyhe.mirai.plugin.service.PlayerListService;
import fun.boomcat.luckyhe.mirai.plugin.service.PlayerListServiceImpl;
import fun.boomcat.luckyhe.mirai.plugin.utils.CommandMappingUtil;
import fun.boomcat.luckyhe.mirai.plugin.utils.CommandMappingWebThread;
import fun.boomcat.luckyhe.mirai.plugin.utils.OpCommandHelp;
import kotlin.Unit;
import kotlin.coroutines.Continuation;
import net.mamoe.mirai.console.command.CommandManager;
import net.mamoe.mirai.console.command.CommandOwner;
import net.mamoe.mirai.console.command.CommandSender;
import net.mamoe.mirai.console.command.RawCommand;
import net.mamoe.mirai.console.permission.Permission;
import net.mamoe.mirai.contact.User;
import net.mamoe.mirai.message.data.At;
import net.mamoe.mirai.message.data.MessageChain;
import net.mamoe.mirai.message.data.PlainText;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

public class OpCommand extends RawCommand {

    public OpCommand(@NotNull CommandOwner owner, @NotNull String primaryName, @NotNull String[] secondaryNames, @NotNull String usage, @NotNull String description, @NotNull Permission parentPermission, boolean prefixOptional) {
        super(owner, primaryName, secondaryNames, usage, description, parentPermission, prefixOptional);
    }

    @Nullable
    @Override
    public Object onCommand(@NotNull CommandSender commandSender, @NotNull MessageChain messageChain, @NotNull Continuation<? super Unit> continuation) {
        int mcLen = messageChain.toArray().length;
        String commandPrefix = CommandManager.INSTANCE.getCommandPrefix();
        String primaryName = this.getPrimaryName();
        String[] secondaryNames = this.getSecondaryNames();

        if (mcLen == 0) {
            commandSender.sendMessage(OpCommandHelp.helpStr(primaryName, secondaryNames));
            return null;
        }

        String operation = messageChain.get(0).toString();

        switch (operation.toLowerCase()) {
            case "init":
            case "初始化":
                onInit(commandSender, primaryName, secondaryNames);
                break;

            case "setmcid":
            case "设置mcid":
                onSetMcId(
                        commandSender,
                        Arrays.copyOfRange(messageChain.toArray(), 1, mcLen),
                        primaryName,
                        secondaryNames
                );
                break;
            case "addmap":
            case "添加映射":
                onAddMap(
                        commandSender,
                        Arrays.copyOfRange(messageChain.toArray(), 1, mcLen),
                        primaryName,
                        secondaryNames
                );
                break;
            case "delmap":
            case "删除映射":
                onDelMap(
                        commandSender,
                        Arrays.copyOfRange(messageChain.toArray(), 1, mcLen),
                        primaryName,
                        secondaryNames
                );
                break;
            case "listmap":
            case "所有映射":
                onListMap(
                        commandSender,
                        primaryName,
                        secondaryNames
                );
                break;
            default:
                commandSender.sendMessage("有奇怪的参数，" + commandPrefix + primaryName + "查看帮助");
                return null;
        }

        return null;
    }

    private void onInit(CommandSender commandSender, String primaryName, String[] secondaryNames) {
        PlayerListService playerListService = new PlayerListServiceImpl();
        try {
            playerListService.createRconCommandDB();
            commandSender.sendMessage("创建数据库完成！");
        } catch (Exception e) {
            e.printStackTrace();
            commandSender.sendMessage("创建数据库失败：" + e.toString());
        }

        try {
            playerListService.createPlayerListTable();
            commandSender.sendMessage("创建玩家映射表完成！");
        } catch (Exception e) {
            e.printStackTrace();
            commandSender.sendMessage("创建玩家映射表失败：" + e.toString());
        }

        CommandMappingService commandMappingService = new CommandMappingServiceImpl();
        try {
            commandMappingService.createCommandMappingTable();
            commandSender.sendMessage("创建指令映射表完成！");
        } catch (Exception e) {
            e.printStackTrace();
            commandSender.sendMessage("创建指令映射表失败：" + e.toString());
        }
    }

    private void onSetMcId(CommandSender commandSender, Object[] args, String primaryName, String[] secondaryNames) {
        int argLen = args.length;
        if (argLen != 2) {
            commandSender.sendMessage(OpCommandHelp.setMcIdHelpStr(primaryName, secondaryNames));
            return;
        }

        Object qqSource = args[0];
        Object mcidSource = args[1];
        long qq;
        String mcid;

        if (qqSource instanceof At) {
            At at = (At) qqSource;
            qq = at.getTarget();
        } else {
            try {
                qq = Long.parseLong(qqSource.toString());
            } catch (Exception e) {
                e.printStackTrace();
                commandSender.sendMessage("错误：qq应为数字");
                return;
            }
        }

        if (!(mcidSource instanceof PlainText)) {
            commandSender.sendMessage("错误：mcid应为纯文本");
            return;
        }

        mcid = mcidSource.toString();

        Player player = new Player();
        player.setQq(qq);
        player.setMcId(mcid);
        player.setChecked(true);

        PlayerListService service = new PlayerListServiceImpl();

        try {
            int res = service.insertOnePlayer(player);
            if (res != 1) {
                commandSender.sendMessage("插入失败，请联系开发者");
                return;
            }
        } catch (Exception e) {
            e.printStackTrace();
            commandSender.sendMessage("错误：插入失败");
            return;
        }

        commandSender.sendMessage("插入成功");
    }

    private CommandMapping getCommandMapping(CommandSender commandSender, Object[] args) {
        StringBuilder source = new StringBuilder(),
                mapping = new StringBuilder(),
                description = new StringBuilder();
        List<String> sourceArgs = new ArrayList<>(),
                mappingArgs = new ArrayList<>();

        //        获取内容
        int current = -1;
        int[] filled = new int[3];
        User user = commandSender.getUser();
        long qq = user == null ? 0 : user.getId();

        for (Object message : args) {
            String msg = message.toString();

            switch (msg) {
                case "-s":
                    current = 0;
                    filled[0] += 1;
                    continue;
                case "-m":
                    current = 1;
                    filled[1] += 1;
                    continue;
                case "-d":
                    current = 2;
                    filled[2] += 1;
                    continue;
            }

            switch (current) {
                case 0:
                    source.append(msg).append(" ");
                    if (CommandMappingUtil.isArg(msg)) {
                        sourceArgs.add(msg);
                    }
                    break;
                case 1:
                    mapping.append(msg).append(" ");
                    if (CommandMappingUtil.isArg(msg)) {
                        mappingArgs.add(msg);
                    }
                    break;
                case 2:
                    description.append(msg).append(" ");
                    break;
            }
        }

        //        检查参数重复
        for (int i = 0; i < filled.length; i++) {
            if (filled[i] > 1) {
                switch (i) {
                    case 0:
                        commandSender.sendMessage("错误：出现了多于一个-s参数");
                        return null;
                    case 1:
                        commandSender.sendMessage("错误：出现了多于一个-m参数");
                        return null;
                    case 2:
                        commandSender.sendMessage("错误：出现了多于一个-d参数");
                        return null;
                }
            }

            if (filled[i] < 1) {
                commandSender.sendMessage("错误：缺少参数");
                return null;
            }
        }

        //        检查映射参数
        for (String mappingArg : mappingArgs) {
            if (!sourceArgs.contains(mappingArg)) {
                if (!mappingArg.equals("#{playername}")) {
                    commandSender.sendMessage("错误：参数" + mappingArg + "不在从玩家接收的指令参数中");
                    return null;
                }
            }
        }

        CommandMapping commandMapping = new CommandMapping();
        commandMapping.setQq(qq);
        commandMapping.setSource(source.toString().trim());
        commandMapping.setMapping(mapping.toString().trim());
        commandMapping.setDescription(description.toString().trim());

        return commandMapping;
    }

    private void onAddMap(CommandSender commandSender, Object[] args, String primaryName, String[] secondaryNames) {
        int argLen = args.length;
        if (argLen == 0) {
            commandSender.sendMessage(OpCommandHelp.addMapHelpStr(primaryName, secondaryNames));
            commandSender.sendMessage(OpCommandHelp.addMapExampleStr(primaryName, secondaryNames));
            return;
        }

        CommandMapping commandMapping = getCommandMapping(
                commandSender,
                args
        );

        if (commandMapping == null) {
            return;
        }

        CommandMappingService commandMappingService = new CommandMappingServiceImpl();

        try {
            CommandMapping commandMapping1 = commandMappingService.selectSameSourceCommandMapper(commandMapping.getSource());
            if (commandMapping1 != null) {
                throw new Exception("已存在相同条目");
            }
        } catch (Exception e) {
            e.printStackTrace();
            commandSender.sendMessage("错误：插入失败，请重试");
            return;
        }

        try {
            commandMappingService.insertOneCommandMapping(commandMapping);
        } catch (Exception e) {
            e.printStackTrace();
            commandSender.sendMessage("错误：插入失败，请重试");
            return;
        }

        commandSender.sendMessage("插入数据库成功");
    }

    private void onDelMap(CommandSender commandSender, Object[] args, String primaryName, String[] secondaryNames) {
        int argLen = args.length;
        if (argLen == 0) {
            commandSender.sendMessage(OpCommandHelp.delMapHelpStr(primaryName, secondaryNames));
            return;
        }

        CommandMapping commandMapping = getCommandMapping(commandSender, args);
        CommandMappingService service = new CommandMappingServiceImpl();

        if (commandMapping == null) {
            return;
        }

        try {
            CommandMapping mapping = service.selectSameSourceCommandMapper(commandMapping.getSource());
            if (mapping == null) {
                throw new Exception("数据库中没有该条目");
            }

            int res = service.delOneCommandMapping(commandMapping);
            if (res == 0) {
                throw new Exception("删除失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            commandSender.sendMessage("错误：删除失败，请重试");
            return;
        }

        commandSender.sendMessage("删除成功");
    }

    private void onListMap(CommandSender commandSender, String primaryName, String[] secondaryNames) {
        try {
            CommandMappingWebThread.showAllCommandMappings();
            Map<String, String> webMap = RconCommandConfigOperation.getWebsiteInfo();
            String host = webMap.get("host");
            int port = Integer.parseInt(webMap.get("port"));

            String res = "点击查看：http://" + host + ":" + port;
            commandSender.sendMessage(res);
        } catch (Exception e) {
            e.printStackTrace();
            commandSender.sendMessage("错误：操作失败，请重试");
        }
    }
}
